package totask.config;


import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import totask.response.ResponseData;

import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;

@Order(80)
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * MethodArgumentNotValidException异常：
     *      当 @Validated 修饰 java 对象时，如 (@RequestBody @Validated LoginDto loginDto)
     *      此时当 javabean 中的属性验证失败时，会抛出所有不符合属性的msg
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResponseData handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        // 日志将所有错误信息完全打印出来
        StringBuilder errorLog = new StringBuilder("校验失败——");
        // 定义返回给前端的内容，只返回给前端最先报错的信息
        String msg = bindingResult.getFieldError().getDefaultMessage();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorLog.append(fieldError.getField()).append("：").append(fieldError.getDefaultMessage()).append(", ");
        }
        return new ResponseData().fail(400,msg);
    }

    /**
     * ConstraintViolationException异常：
     *      当 @Validated 修饰单个参数时（此时 @Validated 在类上而不是在方法中），
     *      会抛出ConstraintViolationException异常。
     *      
     * @param ex
     * @return
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public ResponseData handleConstraintViolationException(ConstraintViolationException ex) {
        String message = ex.getMessage();
        /*
        处理格式。
        ex.getMessage() 格式为：方法名.参数名: message
        如：sendEmail.email: 邮箱格式错误，表示是  sendEmail 方法的 email 参数格式校验错误。
         */
        String msg = message.substring(message.indexOf(":") + 1).trim();
        return new ResponseData().fail(400,msg);
    }

	/**
     * 处理异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    public ResponseData validationExceptionHandler(BindException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<String> errorList = new ArrayList<>();
        String msg = bindingResult.getFieldError().getDefaultMessage();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorList.add(fieldError.getDefaultMessage());
        }
        return new ResponseData().fail(400,msg);
    }
}
